package de.fhhannover.inform.hnefatafl.gui;

import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import de.fhhannover.inform.hnefatafl.spiel.Board;
import de.fhhannover.inform.hnefatafl.spiel.MoveChecker;
import de.fhhannover.inform.hnefatafl.vorgaben.BoardContent;
import de.fhhannover.inform.hnefatafl.vorgaben.Cell;
import de.fhhannover.inform.hnefatafl.vorgaben.Move;

public class GamePanel extends JPanel implements Observer,MouseListener,MouseMotionListener{

	private static final long serialVersionUID = -8860204251354754377L;
	
	JButton     		beenden;
	LogPanel			logPanel;
	OptionPanel 		optionPanel;
	String      		attackerName,
						defenderName;
	boolean     		isAttackerHuman,
						isDefenderHuman,
						hasAttackerWon,
						hasDefenderWon,
						startbuttonPushed,
						isAttackersTurn;
	Cell	 			stonePositions[][] = null,
						source, 
						destination;
	int 				mousePosX,
						mousePosY;		
	Move 				move;
	private BufferedImage 	background,
							field ,
							specialField,
							defender, 
							king,
							attacker,
							logo_attacker,
							logo_defender,
							logo_defender_won,
							logo_attacker_won;
	
	public GamePanel(){
		this.setSize(800,600);
		GridBagLayout thisLayout = new GridBagLayout();
		this.setLayout(thisLayout);
		this.setPreferredSize(new java.awt.Dimension(800, 600));
		this.setOpaque(false);
		
		try {
			   background        = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_hintergrund1_3.png"));
			   field	         = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Feld.png"));
			   specialField      = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_SpecialFeld.png"));
			   defender		     = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Defender.png"));
			   king			     = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_King.png"));
			   attacker		     = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Attacker.png"));
			   logo_attacker     = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Logo_Schwarz.png"));
			   logo_defender     = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Logo_Weiss.png"));
			   logo_defender_won = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Logo_Verteidiger_siegen.png"));
			   logo_attacker_won = ImageIO.read(ImageIO.class.getResource("/res/hnefatafl_Logo_Angreifer_siegen.png"));
			}
			catch(IOException ex) {
			   System.out.println("Ausnahmefehler beim Laden einer Grafik!\nEine Grafik konnte nicht gelesen werden!");
			   ex.printStackTrace();
			}
			catch(IllegalArgumentException ex) {
			   System.out.println("Ausnahmefehler beim Laden einer Grafik!\nEine Grafik wurde nicht gefunden!");
			   ex.printStackTrace();
			}
		
		addMouseListener(this);
		addMouseMotionListener(this);
		
		thisLayout.rowWeights = new double[] {0.0, 0.1, 0.0, 0.1};
		thisLayout.rowHeights = new int[] {113, 7, 277, 7};
		thisLayout.columnWeights = new double[] {0.0, 0.1, 0.1, 0.1};
		thisLayout.columnWidths = new int[] {554, 7, 7, 7};
		
		optionPanel = new OptionPanel();
		if(startbuttonPushed == false){
			this.add(optionPanel,new GridBagConstraints(3, 2, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0, 0));
		}
		
		
		try {
			logPanel = new LogPanel();
			this.add(logPanel, new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		//Beendenknopf
		beenden = new JButton("Beenden");
		this.add(beenden, new GridBagConstraints(3, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
		beenden.setPreferredSize(new java.awt.Dimension(177, 57));
		
		beenden.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				GUIController.getInstance().exitGame();		
			}});
		
		//Startknopf
		optionPanel.gameStarter.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				startbuttonPushed = true;
				attackerName = optionPanel.attackerOption.nameField.getText();
				defenderName = optionPanel.defenderOption.nameField.getText();
				if(optionPanel.attackerOption.attackerOption1.isSelected()){
					isAttackerHuman = true;
				}else if(optionPanel.attackerOption.attackerOption2.isSelected()){
					isAttackerHuman = false;
				}
				if(optionPanel.defenderOption.defenderOption1.isSelected()){
					isDefenderHuman = true;
				}else if(optionPanel.defenderOption.defenderOption2.isSelected()){
					isDefenderHuman = false;
				}
				GUIController.getInstance().initialGame(attackerName,defenderName,isAttackerHuman,isDefenderHuman,optionPanel.slider.getValue());		
				}});
	
	}
	
	//klickposition in Cellobjekt umwandeln
	private GUIField toField(int xpos, int ypos){
		GUIField pos = null;
		int spalte = -1;
		int reihe =  -1;
		if((xpos >= 25 && xpos <= 415)){
			if(xpos * 13 / 390 == 1){
				spalte = 0;
			}else if(xpos * 13 / 390 == 2){
				spalte = 1;
			}else if(xpos * 13 / 390 == 3){
				spalte = 2;
			}else if(xpos * 13 / 390 == 4){
				spalte = 3;
			}else if(xpos * 13 / 390 == 5){
				spalte = 4;
			}else if(xpos * 13 / 390 == 6){
				spalte = 5;
			}else if(xpos * 13 / 390 == 7){
				spalte = 6;
			}else if(xpos * 13 / 390 == 8){
				spalte = 7;
			}else if(xpos * 13 / 390 == 9){
				spalte = 8;
			}else if(xpos * 13 / 390 == 10){
				spalte = 9;
			}else if(xpos * 13 / 390 == 11){
				spalte = 10;
			}else if(xpos * 13 / 390 == 12){
				spalte = 11;
			}else if(xpos * 13 / 390 == 13){
				spalte = 12;
			}
		}else{
			spalte = -1;
		}
		if(ypos >= 25 && ypos <= 415){
			if(ypos * 13 / 390 == 1){
				reihe = 0;
			}else if(ypos * 13 / 390 == 2){
				reihe = 1;
			}else if(ypos * 13 / 390 == 3){
				reihe = 2;
			}else if(ypos * 13 / 390 == 4){
				reihe = 3;
			}else if(ypos * 13 / 390 == 5){
				reihe = 4;
			}else if(ypos * 13 / 390 == 6){
				reihe = 5;
			}else if(ypos * 13 / 390 == 7){
				reihe = 6;
			}else if(ypos * 13 / 390 == 8){
				reihe = 7;
			}else if(ypos * 13 / 390 == 9){
				reihe = 8;
			}else if(ypos * 13 / 390 == 10){
				reihe = 9;
			}else if(ypos * 13 / 390 == 11){
				reihe = 10;
			}else if(ypos * 13 / 390 == 12){
				reihe = 11;
			}else if(ypos * 13 / 390 == 13){
				reihe = 12;
			}
		}else{
			reihe = -1;
		}
		pos = new GUIField(spalte,reihe);
		return pos;
	}
	
	private void renderField(Graphics g,int posx,int posy){
		g.drawImage(field, posx, posy, this);
	}
	
	private void markSpecialSpots(Graphics g,int posx,int posy){
		g.drawImage(specialField, posx, posy, this);
	}
	
	private void renderAttacker(Graphics g, Cell[][] pos){
		if(pos != null){
			for(int i = 1; i < 14; i++){
				for(int j = 1; j < 14; j++){
					if(pos[i][j].getContent() == BoardContent.ATTACKER){
						int x = 24 + ((j-1) * 30);
						int y = 24 + ((i-1) * 30);
						g.drawImage(attacker, x, y, this);
					}
				}
			}
		}
		
	}
	
	private void renderDefender(Graphics g, Cell[][] pos){
		if(pos != null){
		for(int i = 1; i < 14; i++){
			for(int j = 1; j < 14; j++){
				if(pos[i][j].getContent() == BoardContent.DEFENDER){
					int x = 24 + ((j-1) * 30);
					int y = 24 + ((i-1) * 30);
					g.drawImage(defender, x, y, this);
				}
			}
		}
		}
		
	}
	
	private void renderKing(Graphics g, Cell[][] pos) {
		if (pos != null) {
			for (int i = 1; i < 14; i++) {
				for (int j = 1; j < 14; j++) {
					if (pos[i][j].getContent() == BoardContent.KING) {
						int x = 24 + ((j-1) * 30);
						int y = 24 + ((i-1) * 30);
						g.drawImage(king, x, y, this);
					}
				}
			}
		}

	}
	
	private void renderEmpty(Graphics g, Cell[][] pos){
		if(pos != null){
			for(int i = 1; i < 14; i++){
				for(int j = 1; j < 14; j++){
					if(pos[i][j].getContent() == BoardContent.EMPTY){
						int posx = 25 + ((j-1) * 30);
						int posy = 25 + ((i-1) * 30);
						if(i == 1 && j == 1 ||
						   i == 1 && j == 13||
						   i == 7 && j == 7 ||
						   i ==13 && j == 1 ||
						   i ==13 && j ==13){
									g.drawImage(specialField, posx, posy, this);
								}
						else{
							g.drawImage(field, posx, posy, this);
						}
					}
				}
			}
		}
	}
	
	@Override
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		
		//hintergrund zeichnen
		g.drawImage(background, 0, 0, this);
		
		//falls Spiel gestartet wurde, OptionPanel entfernen und Logo zeichnen
		if(startbuttonPushed){
			this.remove(optionPanel);
			if(!hasAttackerWon && !hasDefenderWon){
				if(isAttackersTurn){
					g.drawImage(logo_attacker, 390, 120, this);
				}
				if(!isAttackersTurn){
					g.drawImage(logo_defender, 390, 120, this);
				}
			}
			if(hasAttackerWon){
				g.drawImage(logo_attacker_won, 390, 120, this);
			}
			if(hasDefenderWon){
				g.drawImage(logo_defender_won, 390, 120, this);
			}
		}
		
		//Spielbrett zeichnen
		int positionx = 25;
		int positiony = 25;
		for(int i = 0; i < 13;i++){
			for(int j = 0; j < 13; j++){
				if(i == 0 && j == 0 ||
				   i == 0 && j == 12||
				   i == 6 && j == 6 ||
				   i == 12&& j == 0 ||
				   i == 12&& j == 12){
					markSpecialSpots(g, positionx, positiony);
					positionx += 30;
				}
				else{
				renderField(g, positionx, positiony);
				positionx += 30;
				}
			}
			positionx = 25;
			positiony += 30;
		}
		renderAttacker	(g, stonePositions);
		renderDefender	(g, stonePositions);
		renderEmpty		(g, stonePositions);
		renderKing		(g, stonePositions);
	}
	
	
	@Override
	public void update(Observable obs, Object arg){
		if(arg instanceof Board){
			stonePositions  = ((Board) arg).getBoard();
			isAttackersTurn = ((Board) arg).getIsAttackersTurn();
			hasAttackerWon  = ((Board) arg).hasAttackerWon();
			hasDefenderWon  = ((Board) arg).hasDefenderWon();
		}
		if(arg instanceof MoveChecker){
			//nichts machen, nur um Log zu aktuallisieren.
		}
		repaint();
		logPanel.readFromLog();
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		mousePosX=e.getX();
		mousePosY=e.getY();
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		mousePosX=e.getX();
		mousePosY=e.getY();
	}
	
	@Override
	public void mousePressed(MouseEvent e) {
		source = toField(mousePosX, mousePosY);	
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		destination = toField(mousePosX, mousePosY);
		move = (Move) new GUIZug(source,destination);
		GUIController.getInstance().makeMove(move);
	}
	
	//werden nicht benutzt
	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}


}
